package com.soup.common.support.filter;

import com.google.common.collect.Maps;
import com.soup.common.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 * Description: 请求日志log
 * </p>
 *
 * @author zhaoyi
 * @create 2017-08-11 23:31
 */
@Slf4j
@Component
@ConfigurationProperties(prefix = "rest.request")
public class RequestLoggerInterceptor extends HandlerInterceptorAdapter {

    private static final String REQUEST_TIME = "requestTime";

    private static final String REQUEST_ID = "requestId";

    /**
     * 请求日志记录开关，默认打开
     * rest:
     *   request:
     *     enable-log: true
     */
    private boolean enableLog = true;

    public void setEnableLog(boolean enableLog) {
        this.enableLog = enableLog;
    }

    /**
     * @param request request
     * @param resp resp
     * @param handler handler
     * 
     * @return boolean
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse resp, Object handler) {
        if (enableLog) {
            Date requestTime = new Date();
            // 生成统一请求id
            String requestId = UUID.randomUUID().toString().replace("-", "");
            request.setAttribute(REQUEST_TIME, requestTime.getTime());
            request.setAttribute(REQUEST_ID, requestId);
            String formatRequestTime = DateUtil.date2Str(requestTime, DateUtil.dateFormateFull);
            log.info("====Request Time: {}, RequestId: {}", formatRequestTime, requestId);
            log.info("Path: {}, Method: {}", request.getServletPath(), request.getMethod());
            log.info("Headers: {}", getHeaderMap(request));
            
            String body = null;
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            try {
                StreamUtils.copy(request.getInputStream(), bout);
                body = bout.toString();
            } catch (IOException e) {
                log.error("request occur error: {}", e.getMessage());
            }

            // log.info("request Body: {}", body);
        }
        
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        if (enableLog) {
            Date completedTime = new Date();
            String completed = DateUtil.date2Str(completedTime, DateUtil.dateFormateFull);
            long requestTime = (long) request.getAttribute(REQUEST_TIME);
            String requestId = (String) request.getAttribute(REQUEST_ID);
            long consuming = completedTime.getTime() - requestTime;
            log.info("====Request Completed Time: {}, Consuming: {}ms, RequestId: {}", completed, consuming, requestId);
        }

        super.afterCompletion(request, response, handler, ex);
    }

    /**
     * 解析request请求头信息
     *
     * @param request HttpServletRequest
     * @return 请求头map
     */
    private Map<String, String> getHeaderMap(HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, String> headerMap = Maps.newConcurrentMap();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headerMap.put(headerName, request.getHeader(headerName));
        }

        return headerMap;
    }
}
